import {
	TAllTypes,
	IBrackets,
	BASE_OPERATE_PRIORITY,
	IOperate,
	ISpecial,
	ICollect
} from './types';
import { safeWhile } from '../tools';
import { FormulaError } from './formula-error';
export function rebuildCaculate(calcArr: TAllTypes[]) {
	let result: TAllTypes[] = [];
	let operates: TAllTypes[] = [];
	for (let i = 0; i < calcArr.length; i++) {
		if (calcArr[i].type === 'value' || calcArr[i].type === 'keyworks' || calcArr[i].type === 'position'
			|| calcArr[i].type === 'rowPosition' || calcArr[i].type === 'colPosition') {
			result.push(calcArr[i]);
			if (operates.length > 0) {
				let preOperate = operates[operates.length - 1];
				if (preOperate.type === 'special') {
					if (preOperate.value === ':') {
						result.push(operates.pop())
					}
				}
				if(preOperate.type === 'link') {
					result.push(operates.pop());
				}
			}
			continue;
		}
		if (calcArr[i].type === 'special' && (calcArr[i] as ISpecial).value === ',') {
			operates.push(calcArr[i]);
			continue;
		}
		if(calcArr[i].type === 'collect') {
			let currentOperate = calcArr[i] as ICollect;
			if (currentOperate.value === '{') {
				operates.push(currentOperate);
				continue;
			}
			safeWhile(() => {
				if (operates.length === 0) {
					throw new FormulaError('#REF!', {errorId: '0147f8c9c585'});
				}
				let tempOpreate = operates.pop() as ICollect;
				if(tempOpreate.type === 'collect' && tempOpreate.value === '{') {
					result.push(operates.pop());
					return true;
				} else {
					result.push(tempOpreate);
				}
				return false;
			})
		}
		if (calcArr[i].type === 'brackets') {
			let currentOperate = calcArr[i] as IBrackets;
			if (currentOperate.value === 'left') {
				operates.push(currentOperate);
				continue;
			}
			safeWhile(() => {
				if (operates.length === 0) {
					throw new FormulaError('#REF!', {errorId: '0147f8c9c585'});
				}
				let tempOpreate = operates.pop() as IBrackets;
				if (tempOpreate.type === 'brackets' && tempOpreate.value === 'left') {
					if (operates.length > 0 && operates[operates.length - 1].type === 'function') {
						result.push(operates.pop());
						if (operates.length > 0 && operates[operates.length - 1].type === 'plusMinus') {
							result.push(operates.pop());
						}
					}
					return true;
				} else {
					result.push(tempOpreate);
				}
				return false;
			});
			if (operates.length > 0 && operates[operates.length - 1].type === 'plusMinus') {
				result.push(operates.pop())
			}
			continue;
		}
		if (calcArr[i].type === 'plusMinus') {
			if (operates.length === 0) {
				operates.push(calcArr[i]);
				continue;
			}
			if (operates[operates.length - 1].type === 'operate') {
				operates.push(calcArr[i]);
				continue;
			}
		}
		if (calcArr[i].type === 'operate') {
			let currentOperate = calcArr[i] as IOperate;
			if (operates.length === 0) {
				operates.push(currentOperate);
				continue;
			}
			let preOperate = operates[operates.length - 1];
			if (preOperate.type === 'plusMinus') {
				result.push(operates.pop());
				continue;
			}
			if (preOperate.type !== 'operate') {
				operates.push(currentOperate);
				continue;
			}

			let priority = BASE_OPERATE_PRIORITY[currentOperate.value];
			safeWhile(() => {
				if (operates.length === 0 || operates[operates.length - 1].type !== 'operate') {
					operates.push(currentOperate);
					return true;
				}
				let prepPriority = BASE_OPERATE_PRIORITY[currentOperate.value];
				if (priority <= prepPriority) {
					operates.push(currentOperate);
					return true;
				} else {
					result.push(operates.pop());
				}
				return false;
			});
		}
		if (calcArr[i].type === 'function') {
			operates.push(calcArr[i]);
		}
		if (calcArr[i].type === 'special') {
			if ((calcArr[i] as ISpecial).value === ':') {
				safeWhile(() => {
					if (operates.length === 0) {
						return true;
					}
					let preOperate = operates[operates.length - 1];
					if (preOperate.type === 'brackets' || preOperate.type === 'operate') {
						return true;
					}
					result.push(operates.pop());
				});
				operates.push(calcArr[i])
			}
			if ((calcArr[i] as ISpecial).value === ',') {
				safeWhile(() => {
					if (operates.length === 0) {
						return true;
					}
					let preOperate = operates[operates.length - 1];
					if (preOperate.type === 'function' || (preOperate.type === 'special' && preOperate.value === ',')) {
						operates.push(calcArr[i]);
						return true;
					}
					result.push(operates.pop());
					return false;
				});
			}
		}
	}
	return result.concat(operates.reverse());
}